java父类获取子类对象、调用子类方法

1.Java中父类能调用子类的方法吗?

答案:能

1.1 实现方式描述

(1)父类中的抽象方法让子类实现并返回
(2)通过注册监听,然后通过回调接口调用子类相关方法
(3)在父类中通过反射调用子类的相关方法
(4)在父类中直接new子类相关对象或者通过构造函数传入子类对象,然后调用其方法
(5)将子类相关方法声明为static,在父类中调用子类的static方法

 

1.2 四种实现方式的代码

方式一:父类中的抽象方法,子类继承父类并实现抽象方法,有返回值,父类就可以拿到子类中的对象或者调用子类的方法。

父类抽象方法:

public abstract class Father {

	protected abstract int getSonData();

	// 父类调用子类方法
	public int getData() {
		return getSonData();
	}

}

子类继承父类并实现抽象方法:

public class Son extends Father {

	private int sonData = 100;

	// 子类实现的父类方法
	@Override
	protected int getSonData() {
		return sonData;
	}

}

测试:

public class Test {
	public static void main(String[] args) {
		Father father = new Son();
		int sonData = father.getData();
		System.out.println("获取子类数据:" + sonData);
	}
}

结果:

获取子类数据:100

方拾二:子类利用接口回调提供给父类数据

父类的接口:

public class Father {
	
	private CallBackListener cBackListener;

	public void setListener(CallBackListener listener) {
		this.cBackListener = listener;
	}
	
	//父类调用子类方法
	public int getSonData() {
		return cBackListener.sonData();
	}

}

interface CallBackListener {
	int sonData();
}

子类实现父类接口:

public class Son extends Father implements CallBackListener{
	
	public void getFather() {
		setListener(this);
	}
	

	//子类实现父类方法
	@Override
	public int sonData() {
		return 2020;
	}

}

测试:

public class Test {
	public static void main(String[] args) {
		Son son = new Son();
		son.getFather();
		int data = son.getSonData();
		System.out.println("从父类获取的子类数据:" + data);
	}
}

结果:

从父类获取的子类数据:2020

方式三、四、五:Son只提供打印方法,Father中通过这三种方式都可以获取到Son的实例对象,就可以完成在父类中调用子类的方法:

子类:

public class Son extends Father{

	public void test(String test) {
		System.out.println(test);
	}
	
	public static void testStatic() {
		System.out.println("static test");
	}
}

父类:

public class Father {

	/**
	 * 通过new son() 直接获取子类实例
	 */
	public void callSonMethod_newSon() {
		Son son = new Son();
		son.test("通过new Son()获取子类实例");
	}

	/**
	 * 通过反射获取子类实例
	 */
	public void callSonMethod_reflection() {
		try {
			Class clazz = Class.forName("other.Son");
			Son son = (Son) clazz.newInstance();
			son.test("通过反射获取子类实例");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 通过静态变量获取子类实例
	 */
	public void callSonMethod_static() {
		Son.testStatic();
	}

}

测试:

public class test {
	public static void main(String[] args) {
		Father father = new Father();
		father.callSonMethod_newSon();
		father.callSonMethod_reflection();
		father.callSonMethod_static();
	}
}

结果:

通过new Son()获取子类实例
通过反射获取子类实例
static test

2.上述几种实现方式,在实际项目被允许吗?

如果各位看官细细品味了上面的样例代码,并且稍微熟悉面向对象的继承和多态特性的话,会得出一个显而易见的结论,不允许
看到这儿,如果仍有看官,不太明白为什么不允许话,小编只能在上面的样例基础上,简单提醒以下几点,还需各位看官在实际项目研发过程中细细品味 & 时常总结,敬请见谅。因为毕竟涉及到面向对象的基本属性、项目经验,有些东西本来就是约定、规则、经验,无法进行明说。

(1)Java继承概念中,父类是不确定子类的,但子类可以确定其父类--多态特性的来源之一
(2)父类是不可调用子类的方法的,但子类可以调用父类所有非private的方法-继承特性的特征之一
(3)存在明显的代码漏洞,例如:因为Java继承的关系,所以类进行加载时,是先加载的父类,才去加载子类,如果恰巧这是父类的某个方法调用了子类的方法,而子类方法的某些常量因为子类还未加载没有实例化,就会直接导致程序崩溃
(4)如果通过上述方法实现了相关效果,那么请这样做的各位Coder反思一个问题,您的子类继承父类的意义到底在哪里?

3.如果在实际项目中,的确有这样的特殊业务场景,即有些实现并不确定,需要具体子类去实现,但是又必须在父类规定其调用顺序与场景,应如何做?

 

package test;

/**
 * 父类
 */
public abstract class Father {
    // 基本方法
    protected abstract void doSomething();

    // 基本方法
    protected abstract void doAnything();

    // 模板方法
    public void templateMethod() {
        /*
         * 调用基本方法,完成相关的逻辑
         */
        this.doAnything();
        this.doSomething();
    }
}

 

package test;


/**
 * 子类
 */
public class Son extends Father{

    @Override
    protected void doSomething() {
        System.out.println("Son doSomething");
    }

    @Override
    protected void doAnything() {
        System.out.println("Son doAnything");
    }

    
}

 

package test;

/**
 * 测试功能类
 * 
 */
public class TestTwo {
    public static void main(String[] args) {
        Son son = new Son();
        son.templateMethod();
    }
}

基本方法:基本方法也叫做基本操作,是由子类实现的方法,并且在模板方法中被调用。
模板方法:可以有一个或者几个,一般是具体的方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑。

优点:
● 封装不变部分,扩展可变部分
● 提取公共部分代码,便于维护
● 行为由父类控制,子类实现

缺点:
按照我们的设计习惯,抽象类负责声明最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法。但是模板方法模式却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度,而且也会让新手产生不适感。

参考: https://www.jianshu.com/p/204e5d76ec11

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值